import { VuexModule, Module, Action, Mutation, getModule, config } from "vuex-module-decorators";
import { getToken, setToken, removeToken } from "@/utils/cookies";
import router, { resetRouter } from "@/router";
import { PermissionModule } from "./permission";
import store from "@/store";
import { decodeToken, decrypt, Token } from '@/utils/auth';
import { apiGetSelfUser, apiRefreshToken, apiGetSystemUser, login } from "@/api/tunnyApi";
import SystemTunnyApi from "@/api/systemTunnyApi"
import { getUserPermission } from "@/api/cloudTunnyApi"
import { logout } from "@/api/tunnyApi";
import jwt_decode from "jwt-decode";
import { Message } from "element-ui";
import { encrypt } from '../../utils/auth';
// 给每个@Action都加上rawError = true，显示异常信息
config.rawError = true
export class LoginForm {
  constructor(
    username: string,
    public password: string,
    public authmode: string
  ) {
    this.username = username;
  }

  public username: string
}

export interface IAuthState {
  token: string;
  userId: number;
  username: string;
  avatar: string;
  authmode: string;
  authrole: string;
  cloud_tenant_id: number | undefined;
  authGetTime: Date;
  roles: string[];
  userInfo: any | undefined;
  cloud_manage_tenant_id: number | undefined; // 租户管理员使用的cloud—tenant-id
  cloud_manage_username: string; // 租户管理员使用的username
  is_cloud_manage_tenant_system: boolean; // 是否为租户管理员
}

const getTokenData = (): any => {
  const token = getToken();
  if (!token) return {};
  return jwt_decode(decodeToken(token));
}

@Module({ dynamic: true, store, name: "auth" })
class Auth extends VuexModule implements IAuthState {
  public token = getToken() || "";
  public userId = NaN;
  public username = "";
  public avatar = "";
  public authmode = "";
  public authrole = process.env.VUE_APP_AUTH_RULE || 'system_admin';
  public cloud_tenant_id = getTokenData()?.cloud_tenant_id;
  public authGetTime = new Date();
  public roles: string[] = [];
  public userInfo = localStorage.userInfo ? JSON.parse(localStorage.userInfo) : {};
  public cloud_manage_tenant_id = NaN // 租户管理员使用的cloud—tenant-id
  public cloud_manage_username = ""; // 租户管理员使用的username
  public is_cloud_manage_tenant_system = false; // 是否为租户管理员
  public menus: any[] = [];

  @Mutation
  private SET_TOKEN(token: string) {
    try {
      let decoded: any = {};
      if (token) {
        decoded = jwt_decode(decodeToken(token));
        console.log("！！！！", JSON.stringify(decoded));
        this.authrole = process.env.VUE_APP_AUTH_RULE || 'system_admin';
        // this.authrole = typeof decoded.cloud_tenant_id === 'number' ? 'tenant_admin' : 'system_admin';
        if (this.authrole === "tenant_admin") {
          this.cloud_tenant_id = decoded.cloud_tenant_id;
        }
      }
      this.authGetTime = new Date();
      this.token = token;
    } catch (error) {
      if (this.authrole === "system_admin") {
        AuthModule.LogOut(true);
      } else if (this.authrole === "tenant_admin") {
        AuthModule.LogOut(false);
      }

    }

  }

  @Mutation
  private SET_USER_ID(userId: number) {
    this.userId = userId;
  }

  @Mutation
  private SET_USER_NAME(username: string) {
    this.username = username;
  }

  @Mutation
  private SET_AUTHMODE(authmode: string) {
    this.authmode = authmode;
  }

  @Mutation
  private SET_AUTHROLE(authrole: string) {
    this.authrole = authrole;
  }

  @Mutation
  private SET_ROLES(roles: string[]) {
    this.roles = roles;
  }

  @Mutation
  private SET_USER_INFO(userInfo: any) {
    this.userInfo = userInfo;
    localStorage.userInfo = JSON.stringify(userInfo);
  }

  @Mutation
  private SET_CLOUD_TENANT_ID(id: any) {
    this.cloud_manage_tenant_id = id;
  }

  @Mutation
  private SET_CLOUD_USERNAME(username: string) {
    this.cloud_manage_username = username;
  }

  @Mutation
  private SET_IS_CLOUD_TENANT_SYSTEM(is_tenant_system: boolean) {
    this.is_cloud_manage_tenant_system = is_tenant_system;
  }

  @Mutation
  private SET_MENUS(menus: any[]) {
    this.menus = menus;
  }

  @Action
  public async Login(userInfo: LoginForm) {
    userInfo.password = encrypt(userInfo.password)
    // const res: any = await login(userInfo);
    const systemTunnyApi = new SystemTunnyApi();
    const res: any = await systemTunnyApi.login(userInfo);
    console.log("!!!", res);
    if (!res.error) {
      setToken(res.token);
      this.SET_TOKEN(res.token);
    } else {
      Message.warning(res.message);
      throw new Error(res.message);
    }
  }

  @Action
  public async Refresh() {
    const systemTunnyApi = new SystemTunnyApi();
    const res: any = await systemTunnyApi.refreshToken(this.token);
    // const res: any = await apiRefreshToken(this.token);
    if (res.token) {
      setToken(res.token);
      this.SET_TOKEN(res.token);
      Token.set(res.token);
    } else {
      // this.ResetToken();
      // location.reload();
      if (this.authrole === "tenant_admin") {
        this.LogOut(false);
      } else if (this.authrole === "system_admin") {
        this.LogOut(true);
      }
    }
  }

  @Action
  public ResetToken() {
    removeToken();
    this.SET_TOKEN("");
    this.SET_ROLES([]);
  }
  @Action({ rawError: true })
  public async GetUserInfo() {
    if (this.token === "" && this.is_cloud_manage_tenant_system == false) {
      throw Error("GetUserInfo: token is undefined!");
    }
    let res: any = ""
    if (this.authrole === 'system_admin') {
      const systemTunnyApi = new SystemTunnyApi();
      res = await systemTunnyApi.getSystemUserByToken();
      // res = await apiGetSystemUser();
    } else {
      res = await apiGetSelfUser();
    }

    console.log("getSystemUserByToken", res);

    res.password = "";
    const userAuthInfo = res;

    this.SET_MENUS(res.data.menus.map((menu: any) => menu.menuCode));
    this.SET_USER_ID(userAuthInfo.id);
    this.SET_USER_NAME(userAuthInfo.username ? userAuthInfo.username : userAuthInfo.name);
    this.SET_USER_INFO(res);
    this.SET_AUTHMODE(userAuthInfo.backend);
    this.SET_ROLES(userAuthInfo.roles);
  }

  @Action
  public async ChangeRoles(role: string) {
    // Dynamically modify permissions
    const token = role + "-token";
    this.SET_TOKEN(token);
    setToken(token);
    await this.GetUserInfo();
    resetRouter();
    // Generate dynamic accessible routes based on roles
    // PermissionModule.GenerateRoutes({ roles: this.roles, permissions: this.permissions });
    // Add generated routes
    router.addRoutes(PermissionModule.dynamicRoutes);
  }

  /**
   * 2021-12-20 系统管理员登出没有产生日志，是因为登出时没有调用logout接口，因此注释了系统管理员原本的登出逻辑，改为了调用接口后，清除token、重制路由、跳转到系统管理员登录页面，尽量不影响租户管理员逻辑
   * @param flag 系统管理员或者租户管理员的标识位，true表示系统管理员，false表示租户管理员
   */
  @Action
  public LogOut(flag: boolean | undefined) {
    // if (this.token === "") {
    //   throw Error("LogOut: token is undefined!");
    // }
    const callback = (res?: any) => {
      removeToken();

      this.SET_TOKEN("");
      this.SET_ROLES([]);
      this.SET_AUTHROLE("");

      // resetRouter();
      // setTimeout(() => {
      //   if(this.authrole === 'system_admin'){
      //     location.href = !this.authrole ? "/system/#/login/system_admin" : (this.authrole === 'system_admin' ? "/system/#/login/system_admin" : "/");
      //   } else {
      //     if (res) {
      //       window.location.href = res;
      //     } else {
      //       location.href = '/system/#/login/system_admin'
      //     }
      //   }
      // }, 0);
      window.location.href = "/system/#/login/system_admin";
      window.location.reload();
    }

    if (flag) {
      // removeToken();

      // this.SET_TOKEN("");
      // this.SET_ROLES([]);
      // // this.SET_AUTHROLE("");

      // resetRouter();
      // window.location.href = "/system/#/login/system_admin";
      if (this.token) {
        logout().finally(() => callback());
      } else {
        callback();
      }
    } else {
      let res = `${(window as any).context.$url_prefix}/home/`;
      removeToken();

      this.SET_TOKEN("");
      this.SET_ROLES([]);
      this.SET_AUTHROLE("");

      resetRouter();
      window.location.href = res;
      // logout().then((res: any) => {
      //   callback(res);
      // }).catch(()  => {
      //   callback();
      // });
    }
  }

  @Action
  public SetToken(token: string) {
    if (token) {
      this.SET_TOKEN(token);
      this.GetUserInfo();
    }
  }

  @Action
  public async getUserPermission() {
    try {
      const res: any = await getUserPermission();
      if (res.id) {
        this.SET_CLOUD_TENANT_ID(res.id);
        this.SET_CLOUD_USERNAME(res.name);
        this.SET_IS_CLOUD_TENANT_SYSTEM(true);
      }
    } 
    catch(err) {
      if (err.code == 403) {
        router.push('/notopened');
        throw err;
      }
    }
  }

  @Action
  public SetCloudTenantId(id: any) {
    this.SET_CLOUD_TENANT_ID(id);
  }

  @Action
  public SetCloudUsername(username: string) {
    this.SET_CLOUD_USERNAME(username);
  }

  @Action
  public IsCloudTenantSystem(is_tenant_system: boolean) {
    this.SET_IS_CLOUD_TENANT_SYSTEM(is_tenant_system);
  }
}

export const AuthModule = getModule(Auth);
